#ifndef OHOS_VIDEO_ENCODER_H_
#define OHOS_VIDEO_ENCODER_H_

#include <queue>
#include <mutex>
#include "rtc_base/buffer.h"
#include "api/video_codecs/video_encoder.h"
#include "common_video/h264/h264_bitstream_parser.h"
#include "common_video/ohos/ohos_egl_context_manager.h"
#include "common_video/ohos/ohos_gl_drawer.h"
#include <multimedia/player_framework/native_avcodec_base.h>

namespace webrtc {

struct EncoderInputData {
    uint32_t index;
    OH_AVBuffer *mem;
};

struct EncoderInputVideoInfo {
    EncoderInputVideoInfo(int32_t w, int32_t h, int64_t ts, int64_t ntp_ts, uint32_t rtp_ts, VideoRotation r) {
        width = w;
        height = h;
        timestamp_us = ts;
        ntp_timestamp_ms = ntp_ts;
        rtp_timestamp = rtp_ts;
        rotation = r;
    }
    int32_t width;
    int32_t height;
    int64_t timestamp_us;
    int64_t ntp_timestamp_ms;
    uint32_t rtp_timestamp;
    VideoRotation rotation;
};

class OhosVideoEncoder : public VideoEncoder {
public:
    OhosVideoEncoder();
    ~OhosVideoEncoder() override;
    int32_t InitEncode(const VideoCodec* codec_settings, const Settings& settings) override;
    int32_t Encode(const VideoFrame &input_image, const std::vector<VideoFrameType> *frame_types) override;
    int32_t RegisterEncodeCompleteCallback(EncodedImageCallback *callback) override;
    void SetRates(const RateControlParameters& rc_parameters) override;
    EncoderInfo GetEncoderInfo() const override;
    int32_t Release() override;
    void OnCodecNeedInputData(uint32_t index, OH_AVBuffer *mem);
    void OnCodecNewOutputData(uint32_t index, OH_AVBuffer *mem);

private:
    int32_t EncodeByteFrame(const VideoFrame &input_image);
    int32_t EncodeTextureFrame(const VideoFrame &input_image);
    int32_t EncodeKeyFrame();
    bool InitGLContext();
    int32_t SetupEncoderInternal();
    void ReleaseEncoderInternal();

private:
    VideoCodec codec_setting_;
    std::string codec_name_ = "";
    OH_AVCodec *oh_video_encoder_{nullptr}; 
    std::queue<EncoderInputData> input_data_queue_;
    std::mutex queue_mutex_;
    std::queue<EncoderInputVideoInfo> input_video_infos_;
    std::mutex infos_mutex_;
    EncodedImageCallback* callback_ = nullptr;
    H264BitstreamParser h264_bitstream_parsers_;
    rtc::BufferT<uint8_t> csd_data_;
    bool active_ = true;
    bool use_surface_ = true;
    OHNativeWindow *native_window_ = nullptr;
    EGLSurface egl_surface_ = EGL_NO_SURFACE;
    std::unique_ptr<EGLRenderContext> gl_context_;
    std::unique_ptr<OhosGLDrawer> gl_drawer_;
    float matrix_[16] {1.0,  0.0, 0.0, 0.0,
                       0.0, -1.0, 0.0, 0.0,
                       0.0,  0.0, 1.0, 0.0,
                       0.0,  0.0, 0.0, 1.0};
    int32_t encoder_stride_w_ = 0;
    int32_t encoder_stride_h_ = 0;
    int min_qp_ = 18;
    int max_qp_ = 51;
};

} // namespace webrtc
#endif //OHOS_VIDEO_ENCODER_H_